

package org.zachary.creditbusiness.hotel.scheduler;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.zachary.commonmodule.entity.MqTransmissionJson;
import org.zachary.creditbusiness.hotel.entity.Reservation;
import org.zachary.creditbusiness.hotel.mapper.ReservationMapper;
import org.zachary.creditbusiness.hotel.util.KafkaProducerService;
import org.zachary.creditbusiness.hotel.util.SendReservation;
import org.zachary.creditbusiness.hotel.util.UUIdUtil;

/**
 * 每天以及应用启动时检测酒店预订，如果当前日期超过截止日期，则将 promise 更新为 2（逾期）
 */
@Component
@Slf4j
public class ReservationExpireScheduler {

    private final ReservationMapper reservationMapper;
    private static final int    DEFAULT_SERVICE_TYPE   = 4;

    private static final DateTimeFormatter FORMATTER =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private KafkaProducerService kafkaProducerService;
    public ReservationExpireScheduler(ReservationMapper reservationMapper) {
        this.reservationMapper = reservationMapper;
    }



    /**
     * 应用启动完成后立即执行一次逾期检测
     */
    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReady() {
        log.info("ApplicationReadyEvent received — running initial expiration check");
        expireReservations();
    }

    /**
     * 每天凌晨 0 点执行逾期检测
     * cron 表达式：秒 分 时 日 月 周
     */
    @Scheduled(cron = "0 0 0 * * *")
    public void scheduledExpirationCheck() {
        log.info("Scheduled expiration check triggered");
        expireReservations();

    }

    /**
     * 执行批量更新：将截止日期早于今天且 promise != 2 的订单标记为逾期
     */
    // 在类中新增或复用一个格式化器
    private static final DateTimeFormatter DTF =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private void expireReservations() {
        LocalDateTime now = LocalDateTime.now();
        log.info("Checking for first-time expirations at {}", now.format(DTF));

        // 1. 先筛选出 promise=0 且 uuid IS NULL 的候选记录
        QueryWrapper<Reservation> qw = new QueryWrapper<>();
        qw.eq("promise", 0)
                .isNull("uuid");
        List<Reservation> candidates = reservationMapper.selectList(qw);

        // 2. 在 Java 里把 String → LocalDateTime，再做时间比较
        List<Reservation> toExpire = new ArrayList<>();
        for (Reservation r : candidates) {
            try {
                LocalDateTime checkout = LocalDateTime.parse(r.getCheckoutDate(), DTF);
                if (checkout.isBefore(now)) {
                    toExpire.add(r);
                }
            } catch (DateTimeParseException e) {
                log.error("Invalid checkoutDate for order {}: {}",
                        r.getOrderId(), r.getCheckoutDate(), e);
            }
        }

        log.info("Found {} reservations to expire", toExpire.size());

        // 3. 对每条“真实逾期”记录，写入 uuid、设 promise=2，并发送一次消息
        for (Reservation r : toExpire) {
            String uuid = UUIdUtil.createUUId();
            r.setUuid(uuid);
            r.setPromise(2);
            reservationMapper.updateById(r);
            sendMessage3(r.getOrderId());
        }

        log.info("Processed {} first-time expirations", toExpire.size());
    }

    public void sendMessage3(Integer orderId) {
        // 1. 查询订单（MyBatis-Plus 自动映射 String 日期字段）
        Reservation res = reservationMapper.selectById(orderId);
        if (res == null) {
            throw new IllegalArgumentException("未找到订单，orderId=" + orderId);
        }

        // 2. 逾期 & 支付状态、金额
        boolean isOverdue = true;
        boolean isPaid    = true;
        double  amount    = 0.00;

        // 3. 转换 String -> Instant（按北京时区）
        Instant dueTime    = parseToInstant(res.getCheckoutDate());
        Instant finishTime = null;

        int overduePeriod=-1;


        // 4. 构建并发送
        MqTransmissionJson payload = new MqTransmissionJson(
                res.getUuid(),
                res.getUserId(),
                DEFAULT_SERVICE_TYPE,
                isOverdue,
                overduePeriod,
                isPaid,
                amount,
                "酒店预订-逾期还款订单",
                dueTime,
                finishTime
                // 刚逾期未还款： isOverdue = true, overduePeriod=-1, isPaid =true , amount=0.0, finishTime=null

        );
        System.out.println("检测到首次逾期");
        kafkaProducerService.sendJsonMessage("TestTopic", payload);
    }
    private Instant parseToInstant(String dateStr) {
        LocalDateTime ldt = LocalDateTime.parse(dateStr, FORMATTER);
        return ldt.atZone(ZoneId.of("Asia/Shanghai")).toInstant();
    }

}